﻿using System;
using System.Data.Entity;
using System.Data.SqlClient;
using System.Threading;
using System.Threading.Tasks;
using AesonBaseFramework.EntityFramework.BaseEntities;
using AesonBaseFramework.EntityFramework.Helpers;

namespace AesonBaseFramework.EntityFramework.DbContexts
{
    public class AesonBaseDbContext : DbContext
    {
        #region field
        public string UserName { get; set; }
        #endregion

        #region Ctor

        // Only for Migration 
        public AesonBaseDbContext()
        {
            this.UserName = "InstallUser";
        }
        //public AesonBaseDbContext(string cn, string user):base(cn)
        //{
        //    this.UserName = user;
        //}

        public AesonBaseDbContext(DbConnectionInfo info)
            : base(ConnectionStringFactory.GetConnectionString(info))
        {
            this.UserName = info.User;
        }

      

        #endregion

        #region Create
        public  static  AesonBaseDbContext Create(DbConnectionInfo info)
        {
            return  new AesonBaseDbContext(info);
        }
        #endregion

        #region Create StoredProcedure
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            // Create All S.P
            modelBuilder.Types().Configure(t => t.MapToStoredProcedures());
        }
        #endregion

        #region Auditing
        public override Task<int> SaveChangesAsync(CancellationToken cancellationToken)
        {
            ApplyAudit(this.UserName);
            return base.SaveChangesAsync(cancellationToken);
        }

        public override int SaveChanges()
        {
            ApplyAudit(this.UserName);
            return base.SaveChanges();
        }

        private void ApplyAudit(string currentUser)
        {

            try
            {
                //ChangeTracker.Entries().Where(e => e.Entity is BaseClass);

                foreach (var auditableEntity in ChangeTracker.Entries<IAesonBaseEntity>())
                {
                    if (auditableEntity.State == EntityState.Added ||
                        auditableEntity.State == EntityState.Modified)
                    {

                        // modify updated date and updated by column for 
                        // adds of updates.
                        auditableEntity.Entity.DateModified = DateTime.Now;
                        auditableEntity.Entity.UserModified = currentUser;

                        // pupulate created date and created by columns for
                        // newly added record.
                        if (auditableEntity.State == EntityState.Added)
                        {
                            auditableEntity.Entity.DateCreate = DateTime.Now;
                            auditableEntity.Entity.UserCreated = currentUser;
                        }
                        else
                        {
                            // we also want to make sure that code is not inadvertly
                            // modifying created date and created by columns 
                            auditableEntity.Property(p => p.DateCreate).IsModified = false;
                            auditableEntity.Property(p => p.UserModified).IsModified = false;
                        }

                    }
                }
            }
            catch (Exception)
            {

              
            }
        }
        #endregion
    }
}
